home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / ae_14.zip / AE.PAS < prev    next >
Pascal/Delphi Source File  |  1991-03-21  |  45KB  |  1,060 lines

  1. program AE ;
  2.  
  3. {$M 16384, 90000, 220000}
  4. { memory requirements: stack size, min heap size, max heap size }
  5.  
  6. {$B-}  { short-circuit boolean evaluation }
  7. {$I-}  { do not generate run-time errors for I/O operations }
  8. {$S+}  { stack checking on }
  9. {$V-}  { relaxed var string checking }
  10.  
  11. uses Crt,Dos,Printer,AE0,AE1,AE2,AE3,AE4 ;
  12.  
  13. const Version = '1.4' ;
  14.       Date    = '21 Mar 1991' ;
  15.  
  16. {-----------------------------------------------------------------------------}
  17. {                                                                             }
  18. { AE -- ANOTHER EDITOR                                                        }
  19. { WRITTEN IN TURBO PASCAL 5.5                                                 }
  20. {                                                                             }
  21. {-----------------------------------------------------------------------------}
  22. { KEY DEFINITIONS                                                             }
  23. {                                                                             }
  24. {           NORMAL                      SHIFT                                 }
  25. {           --------------------------  ------------------------------        }
  26. { F1        HELP                        SETUP                                 }
  27. { F2        SAVE FILE                   WRITE TO FILE                         }
  28. { F3        LOAD FILE                   INSERT FILE                           }
  29. { F4        FIND                        FIND & REPLACE                        }
  30. { F5        PUT MARK                    ERASE MARK                            }
  31. { F6        CUT BLOCK TO PASTE BUFFER   DELETE BLOCK                          }
  32. { F7        COPY BLOCK TO PASTE BUFFER  COMPARE BLOCK TO PASTE BUFFER         }
  33. { F8        PASTE BLOCK                 PRINT BLOCK                           }
  34. { F9        NEXT WINDOW                 PREVIOUS WINDOW                       }
  35. { F10       DOS COMMAND                                                       }
  36. {                                                                             }
  37. { alt 0-9   PLAY MACRO                                                        }
  38. {     A     SWITCH TO WINDOW A                                                }
  39. {     B                                                                       }
  40. {     C     CENTER LINE                                                       }
  41. {     D     DEFINE KEYBOARD MACRO                                             }
  42. {     E     EJECT PRINTER PAGE                                                }
  43. {     F     FORMAT PARAGRAPH                                                  }
  44. {     G     GET SAVED POSITION                                                }
  45. {     H                                                                       }
  46. {     I     IBM CHARACTER SET (ASCII TABLE)                                   }
  47. {     J     JUSTIFY LINE TO RIGHT                                             }
  48. {     K                                                                       }
  49. {     L     DELETE LINE                                                       }
  50. {     M     MATCH BRACKETS                                                    }
  51. {     N     NEW (CLEAR FILE BUFFER)                                           }
  52. {     O                                                                       }
  53. {     P     PRINT ENTIRE FILE BUFFER                                          }
  54. {     R     REPEAT LAST FIND/REPLACE                                          }
  55. {     S     SAVE POSITION                                                     }
  56. {     T     TOGGLE CASE IN BLOCK                                              }
  57. {     V                                                                       }
  58. {     W     DELETE WORD FORWARD                                               }
  59. {     X     EXIT PROGRAM                                                      }
  60. {     Y                                                                       }
  61. {     Z     DISPLAY VERSION NUMBER AND DATE                                   }
  62. {                                                                             }
  63. { FIND/REPLACE OPTIONS: I = IGNORE CASE                                       }
  64. {                       N = NO QUERY                                          }
  65. {                       R = REVERSE SEARCH                                    }
  66. {                                                                             }
  67. { SETUP : E = ENVIRONMENT                                                     }
  68. {                K = KEYCLICK (ON/OFF)                                        }
  69. {                B = BELL (ON/OFF)                                            }
  70. {                W = WORD WRAP LENGTH (0 = OFF)                               }
  71. {                T = TAB SPACING                                              }
  72. {                A = AUTO-INDENT (ON/OFF)                                     }
  73. {                I = INSERT/OVERWRITE                                         }
  74. {         F = FILE                                                            }
  75. {                E = SAVE FILES ON EXIT (ON/OFF)                              }
  76. {                I = INTERVAL FOR AUTO-SAVE (0 = OFF)                         }
  77. {                B = MAKE .BAK FILE (ON/OFF)                                  }
  78. {         P = PRINTER                                                         }
  79. {                P = PAGE LENGTH (0 = OFF)                                    }
  80. {                L = LEFT MARGIN                                              }
  81. {                T = TOP MARGIN                                               }
  82. {                N = PRINT PAGE NUMBERS (ON/OFF)                              }
  83. {         D = DISPLAY                                                         }
  84. {                T = CHANGE CURSOR TYPE                                       }
  85. {                C = CHANGE SCREEN COLORS                                     }
  86. {                D = DISPLAY SPACES AS DOTS (ON/OFF)                          }
  87. {         S = SAVE SETTINGS                                                   }
  88. {                                                                             }
  89. {-----------------------------------------------------------------------------}
  90.  
  91.  
  92. {-----------------------------------------------------------------------------}
  93. { Initializes all necessary variables, and loads the file specified on the    }
  94. { command line into the first workspace.                                      }
  95. {-----------------------------------------------------------------------------}
  96.  
  97. procedure Initialize ;
  98.  
  99. var Reg : registers ;
  100.     Counter : word ;
  101.     ConfigFile : file of ConfigBlock ;
  102.     ConfigFilePath : PathStr ;
  103.     AEDir : DirStr ;
  104.     AEName : NameStr ;
  105.     AEExt : ExtStr ;
  106.  
  107. begin
  108. { check the presence of a color video adapter }
  109. Reg.AH := 15 ;
  110. Intr ($10,Reg) ;
  111. ColorCard := Reg.AL <> Mono ;
  112. { set start address of screen memory }
  113. if ColorCard
  114.    then DisplayPtr := Ptr($B800,0)
  115.    else DisplayPtr := Ptr($B000,0);
  116. { store screen settings }
  117. OrigCursorType := GetCursor ;
  118. OrigTextAttr := TextAttr ;
  119. { try to find setup file }
  120. ConfigFilePath := '' ;
  121. if Exists(ConfigFileName)
  122.    then ConfigFilePath := FExpand (ConfigFileName)
  123.    else begin
  124.         if Lo(DosVersion) >= 3
  125.            then begin
  126.                 { look for setup file in directory where AE.EXE is }
  127.                 FSplit (ParamStr(0),AEDir,AEName,AEExt) ;
  128.                 if Exists (AEDir+ConfigFileName)
  129.                    then ConfigFilePath := AEDir + ConfigFileName ;
  130.                 end
  131.         end ;
  132. if Length(ConfigFilePath) > 0
  133.    then begin
  134.         { load setup }
  135.         Assign (ConfigFile,ConfigFilePath) ;
  136.         Reset (ConfigFile) ;
  137.         Read (ConfigFile,Config) ;
  138.         Close (ConfigFile)
  139.         end
  140.    else begin
  141.         { no setup file: use default }
  142.         Config.Setup := DefaultSetup ;
  143.         for Counter := 1 to NrOfMacros do
  144.             Config.Macro.Length[Counter] := Inactive ;
  145.         end ;
  146. { set screen colors and cursor }
  147. if (not ColorCard) and (Config.Setup.ScreenColors > 2)
  148.    then { on monochrome card only color settings 1 and 2 are valid }
  149.         Config.Setup.ScreenColors := 1 ;
  150. TextAttr := ScreenColorArray[Config.Setup.ScreenColors].NormAttr ;
  151. ClrScr ;
  152. OldCursorPosAttr := TextAttr ;
  153. SetCursor (Config.Setup.Cursortype) ;
  154. { initialize paste buffer, macro stack and several global variables }
  155. New (PasteBuffer) ;
  156. PasteBuffersize := 0 ;
  157. MacroStackpointer := Inactive ;
  158. MacroDefining := Inactive ;
  159. FindString := '' ;
  160. ReplaceString := '' ;
  161. SearchOptions := '' ;
  162. SearchType := Find ;
  163. { clear keyboard buffer }
  164. ClearKeyBuffer ;
  165. { initialize workspaces }
  166. Counter := 1 ;
  167. repeat
  168.     New(Workspace[Counter].Buffer) ;
  169.     ClearWorkspace (Counter) ;
  170.     Inc(Counter) ;
  171. until (Counter > MaxNrOfWorkspaces) or (MaxAvail < WsBufSize) ;
  172. NrOfWorkspaces := Counter - 1 ;
  173. CurrentWsnr := 1 ;
  174. if Length(ParamStr(1)) = 0
  175.    then Message ('Another Editor Version '+Version+'. Press F1 for help')
  176.    else begin
  177.         LoadfileName := FExpand(ParamStr(1)) ;
  178.         if Wildcarded(Loadfilename)
  179.            then begin
  180.                 LoadfileName := GetFileFromList(LoadfileName) ;
  181.                 if not EscPressed
  182.                    then LoadFile (LoadfileName) ;
  183.                 end
  184.            else LoadFile (LoadfileName) ;
  185.         end ;
  186. {$IFDEF DEVELOP }
  187. MinMemAvail := MemAvail ;
  188. {$ENDIF }
  189. end ;
  190.  
  191. {-----------------------------------------------------------------------------}
  192. { Restores screen settings before exiting program.                            }
  193. {-----------------------------------------------------------------------------}
  194.  
  195. procedure ShutOff ;
  196.  
  197. begin
  198. SetCursor (OrigCursorType) ;
  199. TextAttr := OrigTextAttr ;
  200. ClrScr ;
  201. end ;
  202.  
  203. {-----------------------------------------------------------------------------}
  204. { Executes the action corresponding to the key number given.                  }
  205. {-----------------------------------------------------------------------------}
  206.  
  207. procedure ExecKey (var KeyNr:word) ;
  208.  
  209. var Counter              : word ;
  210.     OldCurPos            : Position ;
  211.     MacroNumber          : word ;
  212.     NextPos              : Position ;
  213.     BlockStart,BlockStop : word ;
  214.     TabSteps             : word ;
  215.     LineLength,NewSpaces : word ;
  216.  
  217. begin
  218. with Workspace[CurrentWsnr] do
  219.   begin
  220.   case KeyNr of
  221.     331 : { left }
  222.           begin
  223.           if (Buffer^[CurPos.Index-2] = CR) and (Buffer^[CurPos.Index-1] = LF)
  224.              then SkipUp (CurPos,2)
  225.              else SkipUp (CurPos,1) ;
  226.           end ;
  227.     333 : { right }
  228.           begin
  229.           if (Buffer^[CurPos.Index] = CR) and (Buffer^[CurPos.Index+1] = LF)
  230.              then SkipDown (CurPos,2)
  231.              else SkipDown (CurPos,1) ;
  232.           end ;
  233.     328 : { up }
  234.           begin
  235.           LineUp (CurPos) ;
  236.           end ;
  237.     336 : { down }
  238.           begin
  239.           LineDown (CurPos) ;
  240.           end ;
  241.     327 : { Home }
  242.           begin
  243.           Home (CurPos) ;
  244.           end ;
  245.     335 : { End }
  246.           begin
  247.           EndOfLine (CurPos) ;
  248.           end ;
  249.     329 : { PgUp }
  250.           begin
  251.           for Counter := 1 to (NrOfTextLines-1) do
  252.               LineUp (CurPos) ;
  253.           end ;
  254.     337 : { PgDn }
  255.           begin
  256.           for Counter := 1 to (NrOfTextLines-1) do
  257.               LineDown (CurPos) ;
  258.           end ;
  259.     388 : { ^PgUp }
  260.           begin
  261.           CurPos.Index := 1 ;
  262.           CurPos.Linenr := 1 ;
  263.           CurPos.Colnr := 1 ;
  264.           end ;
  265.     374 : { ^PgDn }
  266.           begin
  267.           for Counter := CurPos.Index to BufferSize do
  268.               if Buffer^[Counter] = CR then Inc(CurPos.Linenr) ;
  269.           CurPos.Index := BufferSize ;
  270.           CalculateColnr (CurPos) ;
  271.           end ;
  272.     375 : { ^Home }
  273.           begin
  274.           while CurPos.Linenr > FirstVisiblePos.Linenr
  275.                 do LineUp (CurPos) ;
  276.           Home (CurPos) ;
  277.           end ;
  278.     373 : { ^End }
  279.           begin
  280.           while (CurPos.Linenr < (FirstVisiblePos.Linenr+NrOfTextLines-1)) and
  281.                 (CurPos.Index < BufferSize)
  282.                 do LineDown (CurPos) ;
  283.           Home (CurPos) ;
  284.           end ;
  285.     371 : { ^left }
  286.           begin
  287.           WordUp (CurPos) ;
  288.           end ;
  289.     372 : { ^right }
  290.           begin
  291.           WordDown (CurPos) ;
  292.           end ;
  293.     340 : { shift-F1 }
  294.           begin
  295.           AlterSetup ;
  296.           end ;
  297.     316 : { F2 }
  298.           begin
  299.           SaveFile (CurrentWsnr) ;
  300.           end ;
  301.     341 : { shift-F2 }
  302.           begin
  303.           EnterString (Name,'New file name: ',79,True,True) ;
  304.           if not EscPressed
  305.              then begin
  306.                   Name := FExpand (Name) ;
  307.                   SaveFile (CurrentWsnr) ;
  308.                   end ;
  309.           end ;
  310.     317 : { F3 }
  311.           begin
  312.           if Length (Name) > 0
  313.              then LoadfileName := Name
  314.              else LoadfileName := '*.*' ;
  315.           EnterString (LoadfileName,'Load file: ',79,True,True) ;
  316.           if Wildcarded(LoadfileName) and (not EscPressed)
  317.              then LoadfileName := GetFileFromList (LoadfileName) ;
  318.           if not EscPressed
  319.              then
  320.                begin
  321.                if ChangesMade
  322.                   then
  323.                     begin
  324.                     if Answer ('File has been changed. Save?')
  325.                        then SaveFile (CurrentWsnr) ;
  326.                     end ;
  327.                if not EscPressed
  328.                   then LoadFile (LoadfileName) ;
  329.                end ;
  330.           end ;
  331.     342 : { shift-F3 }
  332.           begin
  333.           LoadfileName := '*.*' ;
  334.           EnterString (LoadfileName,'Insert file: ',79,True,True) ;
  335.           if Wildcarded(LoadfileName) and (not EscPressed)
  336.              then LoadfileName := GetFileFromList (LoadfileName) ;
  337.           if not EscPressed
  338.              then InsertFile (LoadfileName,CurPos) ;
  339.           end ;
  340.     305 : { alt-N }
  341.           begin
  342.           EscPressed := False ;
  343.           if ChangesMade
  344.              then
  345.                begin
  346.                if Answer ('File has been changed. Save?')
  347.                   then SaveFile (CurrentWsnr) ;
  348.                end ;
  349.           if not EscPressed
  350.              then
  351.                begin
  352.                ClearWorkspace (CurrentWsnr) ;
  353.                end ;
  354.           end ;
  355.     318,343,
  356.     275 : { F4,shift-F4,alt-R }
  357.           begin
  358.           if KeyNr <> 275
  359.              then
  360.                begin
  361.                { if block selected: copy block contents to FindString }
  362.                if Mark <> Inactive
  363.                   then begin
  364.                        if Mark < CurPos.Index
  365.                           then begin
  366.                                BlockStart := Mark ;
  367.                                BlockStop := CurPos.Index ;
  368.                                end
  369.                           else begin
  370.                                BlockStart := CurPos.Index ;
  371.                                BlockStop := Mark ;
  372.                                end ;
  373.                        if (BlockStop - BlockStart) <= 255
  374.                           then begin
  375.                                Move (Buffer^[BlockStart],FindString[1],
  376.                                      BlockStop-BlockStart) ;
  377.                                FindString[0] := Chr(BlockStop-BlockStart) ;
  378.                                end ;
  379.                        end ;
  380.                { enter new search parameters }
  381.                EnterString (FindString,'Find: ',255,False,False) ;
  382.                if (KeyNr = 343) and (not EscPressed)
  383.                   then EnterString (ReplaceString,'Replace with: ',
  384.                                     255,False,False) ;
  385.                if not EscPressed
  386.                   then
  387.                     begin
  388.                     if KeyNr = 318
  389.                        then begin
  390.                             EnterString (SearchOptions,'Options (I,R): ',
  391.                                          4,True,True) ;
  392.                             SearchType := Find ;
  393.                             end
  394.                        else begin
  395.                             EnterString (SearchOptions,'Options (I,N,R): ',
  396.                                          4,True,True) ;
  397.                             SearchType := FindAndReplace ;
  398.                             end ;
  399.                     IgnoreCase := Pos ('I',SearchOptions) <> 0 ;
  400.                     ReverseSearch := Pos ('R',SearchOptions) <> 0 ;
  401.                     NoQuery := Pos ('N',SearchOptions) <> 0 ;
  402.                     end ;
  403.                end ;
  404.           if (not EscPressed) or (KeyNr = 275)
  405.              then
  406.                begin
  407.                { start search }
  408.                OldCurPos := CurPos ;
  409.                SearchString (FindString,CurPos) ;
  410.                if not Found
  411.                   then
  412.                     begin
  413.                     CurPos := OldCurPos ;
  414.                     ErrorMessage (15) ;
  415.                     end ;
  416.                if Found and (SearchType = FindAndReplace)
  417.                   then
  418.                     begin
  419.                     { Counter will contain number of replacements made }
  420.                     Counter := 0 ;
  421.                     repeat
  422.                       { show found string if queried replace }
  423.                       Mark := CurPos.Index + Length(FindString) ;
  424.                       if not NoQuery
  425.                          then RedrawScreen ;
  426.                       { determine if string must be replaced }
  427.                       if NoQuery or
  428.                          (Choose ('Y = replace   N = do not replace') = 'Y')
  429.                          then
  430.                            begin
  431.                            { OldCurPos will point to last replaced string }
  432.                            OldCurPos := CurPos ;
  433.                            { replace FindString with ReplaceString }
  434.                            if Length (FindString) >= Length (ReplaceString)
  435.                               then
  436.                                 begin
  437.                                 { adapt buffer size }
  438.                                 Shrink (CurPos.Index,Length(FindString)-
  439.                                                      Length(ReplaceString)) ;
  440.                                 { write ReplaceString }
  441.                                 Move (ReplaceString[1],Buffer^[CurPos.Index],
  442.                                       Length(ReplaceString)) ;
  443.                                 if not ReverseSearch
  444.                                    then
  445.                                      begin
  446.                                      { resume search after ReplaceString }
  447.                                      SkipDown (CurPos,
  448.                                                Length(ReplaceString)) ;
  449.                                      end ;
  450.                                 Inc (Counter) ;
  451.                                 end
  452.                               else
  453.                                 begin
  454.                                 if Grow (CurPos.Index,
  455.                                          Length(ReplaceString) -
  456.                                          Length(FindString))
  457.                                    then
  458.                                      begin
  459.                                      { write ReplaceString }
  460.                                      Move (ReplaceString[1],
  461.                                            Buffer^[CurPos.Index],
  462.                                            Length (ReplaceString)) ;
  463.                                      if not ReverseSearch
  464.                                         then
  465.                                           begin
  466.                                           { resume search after ReplaceString }
  467.                                           SkipDown (CurPos,
  468.                                                     Length(ReplaceString)) ;
  469.                                           end ;
  470.                                      Inc (Counter) ;
  471.                                      end
  472.                                    else
  473.                                      { no room for replace: stop search }
  474.                                      EscPressed := True ;
  475.                                 end ;
  476.                            { show replacement counter }
  477.                            Message (WordToString(Counter,0) +
  478.                                     ' replacement(s) made') ;
  479.                            end ;
  480.                       if not EscPressed
  481.                          then SearchString (FindString,CurPos) ;
  482.                     until (not Found) or EscPressed ;
  483.                     { return to last replaced string }
  484.                     CurPos := OldCurPos ;
  485.                     end ;
  486.                { erase block mark }
  487.                Mark := Inactive ;
  488.                end ;
  489.           end ;
  490.     319 : { F5 }
  491.           begin
  492.           Mark := CurPos.Index ;
  493.           end ;
  494.     344 : { shift-F5 }
  495.           begin
  496.           Mark := Inactive ;
  497.           end ;
  498.     320 : { F6 }
  499.           begin
  500.           if CopyBlock
  501.              then begin
  502.                   DeleteBlock ;
  503.                   end ;
  504.           end ;
  505.     345 : { shift-F6 }
  506.           begin
  507.           DeleteBlock ;
  508.           end ;
  509.     321 : { F7 }
  510.           begin
  511.           if CopyBlock
  512.              then begin
  513.                   Mark := Inactive ;
  514.                   Message ('Block copied into paste buffer') ;
  515.                   end ;
  516.           end ;
  517.     346 : { shift-F7 }
  518.           begin
  519.           if Mark = Inactive
  520.              then ErrorMessage (5)
  521.              else begin
  522.                   if Mark < CurPos.Index
  523.                      then begin
  524.                           BlockStart := Mark ;
  525.                           BlockStop := CurPos.Index ;
  526.                           end
  527.                      else begin
  528.                           BlockStart := CurPos.Index ;
  529.                           BlockStop := Mark ;
  530.                           end ;
  531.                   Counter := BlockStart ;
  532.                   while (Buffer^[Counter] =
  533.                          PasteBuffer^[Counter-BlockStart+1]) and
  534.                         (Counter < BlockStop) do
  535.                         Inc (Counter) ;
  536.                   if (Counter >= BlockStop) and
  537.                      ((BlockStop-BlockStart) = PasteBufferSize)
  538.                      then Message ('Block is equal to paste buffer')
  539.                      else Message ('Block is not equal to paste buffer') ;
  540.                   end ;
  541.           end ;
  542.     322 : { F8 }
  543.           begin
  544.           InsertBlock ;
  545.           end ;
  546.     347 : { shift-F8 }
  547.           begin
  548.           if Mark = Inactive
  549.              then ErrorMessage (5)
  550.              else begin
  551.                   if Mark < CurPos.Index
  552.                      then PrintBlock (Buffer,Mark,CurPos.Index-1)
  553.                      else PrintBlock (Buffer,CurPos.Index,Mark-1) ;
  554.                   end ;
  555.           end ;
  556.     281 : { alt-P }
  557.           begin
  558.           if Answer ('Print entire file buffer?')
  559.              then PrintBlock (Buffer,1,BufferSize-1) ;
  560.           end ;
  561.     323 : { F9 }
  562.           if CurrentWsnr = NrOfWorkspaces
  563.              then CurrentWsnr := 1
  564.              else Inc (CurrentWsnr) ;
  565.     348 : { shift-F9 }
  566.           if CurrentWsnr = 1
  567.              then CurrentWsnr := NrOfWorkspaces
  568.              else Dec (CurrentWsnr) ;
  569.     324 : { F10 }
  570.           begin
  571.           { restore screen settings }
  572.           TextAttr := OrigTextAttr ;
  573.           SetCursor (OrigCursorType) ;
  574.           ClrScr ;
  575.           Writeln ('Type EXIT to return to AE ...') ;
  576.           SwapVectors ;
  577.           Exec (GetEnv('COMSPEC'),'') ;
  578.           SwapVectors ;
  579.           if DosError <> 0
  580.              then ErrorMessage (14) ;
  581.           { reset screen settings }
  582.           TextAttr := ScreenColorArray[Config.Setup.ScreenColors].NormAttr ;
  583.           SetCursor (Config.Setup.CursorType) ;
  584.           end ;
  585.     274 : { alt-E }
  586.           begin
  587.           Write (Lst,FF) ;
  588.           CheckDiskError ;
  589.           end ;
  590.     286 : { alt-A }
  591.           CurrentWsnr := 1 ;
  592.     376..
  593.     385 : { alt-1 .. alt-0 }
  594.           begin
  595.           MacroNumber := KeyNr - 375 ;
  596.           if MacroDefining = MacroNumber
  597.              then begin
  598.                   Dec (Config.Macro.Length[MacroDefining]) ;
  599.                   ErrorMessage (9) ;
  600.                   end
  601.              else begin
  602.                   if Config.Macro.Length[MacroNumber] > 0
  603.                      then begin
  604.                           if MacroStackpointer = MacroStackDepth
  605.                              then begin
  606.                                   MacroStackpointer := Inactive ;
  607.                                   ErrorMessage (10) ;
  608.                                   end
  609.                              else begin
  610.                                   { push macro onto MacroStack }
  611.                                   Inc (MacroStackpointer) ;
  612.                                   with MacroStack[MacroStackpointer] do
  613.                                        begin
  614.                                        Macronr := MacroNumber ;
  615.                                        Index := 1 ;
  616.                                        end ;
  617.                                   end ;
  618.                           end ;
  619.                   end ;
  620.           end ;
  621.     288 : { alt-D }
  622.           begin
  623.           if MacroDefining = Inactive
  624.              then begin
  625.                   { Start define mode }
  626.                   MacroNumber := 1 ;
  627.                   EnterWord (MacroNumber,
  628.                              'Define keyboard Macro nr. (1-10): ',1,10) ;
  629.                   if not EscPressed
  630.                      then begin
  631.                           { reset old macro }
  632.                           Config.Macro.Length[MacroNumber] := 0 ;
  633.                           MacroDefining := MacroNumber ;
  634.                           end ;
  635.                   end
  636.              else { end define mode }
  637.                   MacroDefining := Inactive ;
  638.           end ;
  639.     289 : { alt-F }
  640.           begin
  641.           if Config.Setup.WordWrapLength = Inactive
  642.              then ErrorMessage (11)
  643.              else begin
  644.                   if Buffer^[CurPos.Index] in WordSeparators
  645.                      then WordDown (CurPos) ;
  646.                   NextPos := CurPos ;
  647.                   WordDown (NextPos) ;
  648.                   { NextPos points to start of next word after CurPos }
  649.                   while ((NextPos.Linenr - CurPos.Linenr) < 2) and
  650.                         (CurPos.Index < BufferSize) do
  651.                     begin
  652.                     if NextPos.Linenr > CurPos.Linenr
  653.                        then { replace old CR+LF with spaces }
  654.                             with Nextpos do
  655.                                  begin
  656.                                  Buffer^[Index-Colnr] := ' ' ;
  657.                                  if Buffer^[Index-Colnr-1] = CR
  658.                                     then Buffer^[Index-Colnr-1] := ' ' ;
  659.                                  { NextPos now is on same line as Curpos }
  660.                                  Dec (Linenr) ;
  661.                                  Colnr := CurPos.Colnr +
  662.                                           (Index - CurPos.Index) ;
  663.                             end ;
  664.                     { replace multiple spaces with single space }
  665.                     Counter := 2 ;
  666.                     while Buffer^[NextPos.Index-Counter] = ' ' do
  667.                           Inc (Counter) ;
  668.                     if Counter > 2
  669.                        then with NextPos do
  670.                                  begin
  671.                                  { calculate number of redundant spaces }
  672.                                  Dec (Counter,2) ;
  673.                                  { remove redundant spaces }
  674.                                  Shrink (Index-Counter-1,Counter) ;
  675.                                  { adapt NextPos }
  676.                                  Dec (Index,Counter) ;
  677.                                  Dec (Colnr,Counter) ;
  678.                                  end ; { of if }
  679.                     if NextPos.Colnr > Config.Setup.WordWrapLength
  680.                        then begin
  681.                             { break line at position CurPos }
  682.                             InsertCRLF (CurPos) ;
  683.                             { NextPos is now invalid }
  684.                             WordDown (CurPos) ;
  685.                             NextPos := CurPos ;
  686.                             end
  687.                        else CurPos := NextPos ;
  688.                     { on to next word }
  689.                     WordDown (NextPos) ;
  690.                     end ; { of while }
  691.                   if CurPos.Index < BufferSize
  692.                      then begin
  693.                           { check if last line of paragraph must be broken }
  694.                           NextPos := CurPos ;
  695.                           EndOfLine (NextPos) ;
  696.                           { remove spaces at end of line }
  697.                           Counter := 0 ;
  698.                           while Buffer^[NextPos.Index-1] = ' ' do
  699.                                 begin
  700.                                 Dec (NextPos.Index) ;
  701.                                 Dec (NextPos.Colnr) ;
  702.                                 Inc (Counter) ;
  703.                                 end ;
  704.                           Shrink (NextPos.Index,Counter) ;
  705.                           if NextPos.Colnr > Config.Setup.WordWrapLength
  706.                              then InsertCRLF (CurPos) ;
  707.                           end ; { of if }
  708.                   { move to first word in new paragraph }
  709.                   WordDown (CurPos) ;
  710.                   end ;
  711.           end ;
  712. 292,302 : { alt-J, alt-C }
  713.           begin
  714.           if Config.Setup.WordWrapLength = Inactive
  715.              then ErrorMessage (11)
  716.              else begin
  717.                   { measure line length }
  718.                   EndOfLine (CurPos) ;
  719.                   { remove trailing spaces }
  720.                   Counter := 1 ;
  721.                   while (Buffer^[CurPos.Index-Counter] = ' ') and
  722.                         (Counter < CurPos.Colnr) do
  723.                         Inc (Counter) ;
  724.                   Dec (CurPos.Index,Counter-1) ;
  725.                   Dec (CurPos.Colnr,Counter-1) ;
  726.                   Shrink (CurPos.Index,Counter-1) ;
  727.                   LineLength := CurPos.Colnr - 1 ;
  728.                   { remove leading spaces }
  729.                   Home (CurPos) ;
  730.                   Counter := 0 ;
  731.                   while (Buffer^[CurPos.Index+Counter] = ' ') and
  732.                         (Counter <= LineLength) do
  733.                         Inc (Counter) ;
  734.                   Shrink (CurPos.Index,Counter) ;
  735.                   Dec (LineLength,Counter) ;
  736.                   NewSpaces := (Config.Setup.WordWrapLength-LineLength) ;
  737.                   if KeyNr = 302
  738.                      then NewSpaces := NewSpaces div 2 ;
  739.                   if NewSpaces > 0
  740.                      then InsertSpaces (CurPos,NewSpaces) ;
  741.                   end
  742.           end ;
  743.     306 : { alt-M }
  744.           begin
  745.           OldCurPos := CurPos ;
  746.           Found := True ;
  747.           case Buffer^[CurPos.Index] of
  748.                '{' : MatchBracketsDown ('{','}',CurPos) ;
  749.                '}' : MatchBracketsUp ('{','}',CurPos) ;
  750.                '(' : MatchBracketsDown ('(',')',CurPos) ;
  751.                ')' : MatchBracketsUp ('(',')',CurPos) ;
  752.                '[' : MatchBracketsDown ('[',']',CurPos) ;
  753.                ']' : MatchBracketsUp ('[',']',CurPos) ;
  754.                '<' : MatchBracketsDown ('<','>',CurPos) ;
  755.                '>' : MatchBracketsUp ('<','>',CurPos) ;
  756.                else Message ('Cursor must be on bracket ({[<>]})') ;
  757.                end ; { of case }
  758.           if not Found
  759.              then begin
  760.                   Message ('No matching bracket found') ;
  761.                   CurPos := OldCurPos ;
  762.                   end ;
  763.           end ;
  764.     287 : { alt-S }
  765.           begin
  766.           if PosStackpointer = PosStackDepth
  767.              then ErrorMessage (12)
  768.              else begin
  769.                   Inc (PosStackpointer) ;
  770.                   PosStack[PosStackpointer] := CurPos.Index ;
  771.                   end ;
  772.            end ;
  773.     290 : { alt-G }
  774.           begin
  775.           if PosStackpointer = Inactive
  776.              then ErrorMessage (13)
  777.              else begin
  778.                   if CurPos.Index < PosStack[PosStackpointer]
  779.                      then SkipDown (CurPos,
  780.                                     PosStack[PosStackpointer] - CurPos.Index)
  781.                      else SkipUp (CurPos,
  782.                                   CurPos.Index - PosStack[PosStackpointer]) ;
  783.                   Dec (PosStackpointer) ;
  784.                   end ;
  785.           end ;
  786.     276 : { alt-T }
  787.           begin
  788.           if Mark = Inactive
  789.              then ErrorMessage (5)
  790.              else begin
  791.                   if Mark < CurPos.Index
  792.                      then begin
  793.                           BlockStart := Mark ;
  794.                           BlockStop := CurPos.Index ;
  795.                           end
  796.                      else begin
  797.                           BlockStart := CurPos.Index  ;
  798.                           BlockStop := Mark ;
  799.                           end ;
  800.                   for Counter := BlockStart to (BlockStop-1) do
  801.                       if Buffer^[Counter] in ['A'..'Z','a'..'z']
  802.                          then begin
  803.                               Buffer^[Counter] :=
  804.                                      Chr(Ord(Buffer^[Counter]) xor $20) ;
  805.                               ChangesMade := True ;
  806.                               end ;
  807.                   end ;
  808.           end ;
  809.  0..255 : { character-keys }
  810.           begin
  811.           if KeyNr = 26
  812.              then Message ('Warning: Inserting end-of-file character') ;
  813.           if (not Config.Setup.Insertmode) and
  814.              (Buffer^[CurPos.Index] <> CR) and
  815.              (CurPos.Index < Buffersize)
  816.              then begin
  817.                   { overwrite character if not in insertmode and not }
  818.                   { at end of line or buffer }
  819.                   Buffer^[CurPos.Index] := Chr(KeyNr) ;
  820.                   Inc (CurPos.Index) ;
  821.                   if KeyNr = 13
  822.                      then begin
  823.                           Inc (Curpos.Linenr) ;
  824.                           CurPos.Colnr := 1 ;
  825.                           end
  826.                      else Inc (CurPos.Colnr) ;
  827.                   ChangesMade := True ;
  828.                   end
  829.              else begin
  830.                   if Grow (CurPos.Index,1)
  831.                      then begin
  832.                           Buffer^[CurPos.Index] := Chr(KeyNr) ;
  833.                           Inc (CurPos.Index) ;
  834.                           if KeyNr = 13
  835.                              then begin
  836.                                   Inc (Curpos.Linenr) ;
  837.                                   CurPos.Colnr := 1 ;
  838.                                   end
  839.                              else Inc (CurPos.Colnr) ;
  840.                           if (Config.Setup.WordWrapLength <> Inactive) and
  841.                              (CurPos.Colnr > Config.Setup.WordWrapLength)
  842.                              then
  843.                                begin
  844.                                OldCurPos := CurPos ;
  845.                                WordUp (CurPos) ;
  846.                                if Buffer^[CurPos.Index-1] = ' '
  847.                                   then
  848.                                     begin
  849.                                     Shrink (CurPos.Index-1,1) ;
  850.                                     Dec (CurPos.Index) ;
  851.                                     Dec (CurPos.Colnr) ;
  852.                                     Dec (OldCurpos.Index) ;
  853.                                     end ;
  854.                                NextPos := CurPos ;
  855.                                InsertCRLF (CurPos) ;
  856.                                SkipDown (CurPos,
  857.                                          OldCurPos.Index-CurPos.Index+
  858.                                          (CurPos.Index-NextPos.Index)) ;
  859.                                Home (FirstVisiblePos) ;
  860.                                end ;
  861.                           end ;
  862.                   end ;
  863.           end ;
  864. 266,269 : { Enter,^Enter }
  865.           begin
  866.           InsertCRLF (CurPos) ;
  867.           end ;
  868.     265 : { Tab }
  869.           begin
  870.           if Config.Setup.TabSpacing = 0
  871.              then begin
  872.                   { find nearest beginning of word in previous line }
  873.                   OldCurPos := CurPos ;
  874.                   LineUp (Curpos) ;
  875.                   while (CurPos.Colnr <= OldCurPos.Colnr) and
  876.                         (CurPos.Linenr < OldCurpos.Linenr) do
  877.                         WordDown (CurPos) ;
  878.                   if CurPos.Linenr < OldCurpos.Linenr
  879.                      then TabSteps := Curpos.Colnr - OldCurpos.Colnr
  880.                      else TabSteps := 0 ;
  881.                   CurPos := OldCurPos ;
  882.                   end
  883.              else begin
  884.                   TabSteps := Config.Setup.TabSpacing -
  885.                               ((CurPos.Colnr-1) mod Config.Setup.TabSpacing) ;
  886.                   end ;
  887.           if (not Config.Setup.Insertmode)
  888.              then begin
  889.                   { if in overwrite mode: skip tabsteps until eoln or eof }
  890.                   while (TabSteps > 0) and (Buffer^[CurPos.Index] <> CR) and
  891.                         (CurPos.Index < Buffersize) do
  892.                         begin
  893.                         Inc (CurPos.Index) ;
  894.                         Inc (CurPos.Colnr) ;
  895.                         Dec (TabSteps) ;
  896.                         end ;
  897.                   end ; { of if }
  898.           if TabSteps > 0
  899.              then InsertSpaces (CurPos,TabSteps) ;
  900.           end ;
  901.     271 : { shift-Tab }
  902.           begin
  903.           if Config.Setup.TabSpacing = 0
  904.              then begin
  905.                   OldCurPos := CurPos ;
  906.                   LineUp (CurPos) ;
  907.                   EndOfLine (CurPos) ;
  908.                   if CurPos.ColNr > OldCurPos.Colnr
  909.                      then begin
  910.                           Dec (CurPos.Index,CurPos.Colnr-OldCurPos.Colnr) ;
  911.                           CurPos.Colnr := OldCurpos.Colnr ;
  912.                           end ;
  913.                   WordUp (CurPos) ;
  914.                   if CurPos.Linenr = (OldCurpos.Linenr-1)
  915.                      then TabSteps := OldCurpos.Colnr - Curpos.Colnr
  916.                      else TabSteps := OldCurPos.Colnr - 1 ;
  917.                   CurPos := OldCurPos ;
  918.                   end
  919.              else if CurPos.Colnr > Config.Setup.TabSpacing
  920.                      then begin
  921.                           TabSteps := (CurPos.Colnr-1) mod
  922.                                       Config.Setup.TabSpacing ;
  923.                           if TabSteps = 0
  924.                              then TabSteps := Config.Setup.TabSpacing ;
  925.                           end
  926.                      else TabSteps := CurPos.Colnr - 1 ;
  927.           Dec (CurPos.Index,TabSteps) ;
  928.           Dec (CurPos.Colnr,TabSteps) ;
  929.           end ;
  930.     338 : { Ins }
  931.           begin
  932.           Config.Setup.Insertmode := not Config.Setup.Insertmode ;
  933.           end ;
  934.     339 : { Del }
  935.           begin
  936.           if CurPos.Index < Buffersize
  937.              then begin
  938.                   if (Buffer^[CurPos.Index] = CR) and
  939.                      (Buffer^[CurPos.Index+1] = LF)
  940.                      then Shrink (CurPos.Index,2)
  941.                      else Shrink (CurPos.Index,1) ;
  942.                   end ;
  943.           end ;
  944.     264 : { Backspace }
  945.           begin
  946.           if CurPos.Index > 1
  947.              then begin
  948.                   if (Buffer^[CurPos.Index-1] = LF) and
  949.                      (Buffer^[CurPos.Index-2] = CR)
  950.                      then begin
  951.                           SkipUp (CurPos,2) ;
  952.                           Shrink (CurPos.Index,2) ;
  953.                           end
  954.                      else begin
  955.                           SkipUp (CurPos,1) ;
  956.                           Shrink (CurPos.Index,1) ;
  957.                           end ;
  958.                   end ;
  959.           end ;
  960.     273 : { alt-W }
  961.           begin
  962.           NextPos := CurPos ;
  963.           WordDown (NextPos) ;
  964.           if NextPos.Linenr > CurPos.Linenr
  965.              then begin
  966.                   { if start of next word is not on current line }
  967.                   { then delete until next line }
  968.                   NextPos := CurPos ;
  969.                   LineDown (NextPos) ;
  970.                   { only delete CRLF if CurPos is already at end of line }
  971.                   if (NextPos.Index-CurPos.Index) > 2
  972.                      then SkipUp (NextPos,2) ;
  973.                   end ;
  974.           Shrink (CurPos.Index,NextPos.Index-CurPos.Index) ;
  975.           end ;
  976.     294 : { alt-L }
  977.           begin
  978.           Home (CurPos) ;
  979.           NextPos := CurPos ;
  980.           LineDown (NextPos) ;
  981.           Shrink (CurPos.Index,NextPos.Index-CurPos.Index) ;
  982.           end ;
  983.     301 : { alt-X }
  984.           begin
  985.           Counter := 1 ;
  986.           EscPressed := False ;
  987.           while (Counter <= NrOfWorkspaces) and (not EscPressed) do
  988.                 begin
  989.                 with Workspace[Counter] do
  990.                      if ChangesMade
  991.                         then begin
  992.                              if Config.Setup.SaveOnExit
  993.                                 then SaveFile (Counter)
  994.                                 else if Answer('File in '+Chr(64+Counter) +
  995.                                                ' has been changed. Save?')
  996.                                         then begin
  997.                                              SaveFile (Counter) ;
  998.                                              { if save unsuccessful: }
  999.                                              { stop exit procedure }
  1000.                                              if ChangesMade
  1001.                                                 then EscPressed := true ;
  1002.                                              end ;
  1003.                              end ;
  1004.                 Inc (Counter) ;
  1005.                 end ; { of while }
  1006.           { do not exit from program if Escape was pressed }
  1007.           if EscPressed then KeyNr := 0 ;
  1008.           end ;
  1009.     300 : { alt-Z }
  1010.           begin
  1011.           Message ('Another Editor by Dick Alstein.  Version '
  1012.                    + Version + ', ' + Date + '.') ;
  1013.           end ;
  1014.     else  begin
  1015.           WarningBeep ;
  1016.           Message ('This key has no function') ;
  1017.           end ;
  1018.     end  ; { of case }
  1019.   case KeyNr of
  1020.     328,336,329,337 : { up,down,PgUp,PgDn }
  1021.                       begin
  1022.                       { when moving vertically through the buffer: }
  1023.                       { try to make Colnr equal to VirtualColnr }
  1024.                       { (i.e. the value that it "should" have) }
  1025.                       while (CurPos.Colnr < VirtualColnr) and
  1026.                             (Buffer^[CurPos.Index] <> CR) and
  1027.                             (CurPos.Index < BufferSize) do
  1028.                             begin
  1029.                             Inc (CurPos.Index) ;
  1030.                             Inc (CurPos.Colnr) ;
  1031.                             end ;
  1032.                       end ;
  1033.     else              { all other keys }
  1034.                       VirtualColnr := Curpos.Colnr ;
  1035.     end  ; { of case }
  1036.   end ; { of with }
  1037. end ; { of procedure }
  1038.  
  1039. {-----------------------------------------------------------------------------}
  1040.  
  1041. begin
  1042. Initialize ;
  1043. repeat if (not KeyPressed) and (MacroStackPointer = Inactive)
  1044.           then RedrawScreen ;
  1045.        KeyNumber := GetKeynr ;
  1046.        ExecKey (KeyNumber) ;
  1047. until KeyNumber = 301 ; { alt-X }
  1048. ShutOff ;
  1049. {$IFDEF DEVELOP }
  1050. Writeln (MinMemAvail,' bytes always available') ;
  1051. {$ENDIF }
  1052. end.
  1053.  
  1054. {-----------------------------------------------------------------------------}
  1055. { DEVELOP is a compiler directive for compilation during program              }
  1056. { development. It can be used to find out the amount of unused heap           }
  1057. { memory. Set in the Options/Compiler menu, unset for final compilation       }
  1058. {-----------------------------------------------------------------------------}
  1059.  
  1060.